using System;
using System.Collections.Generic;
using System.Text;
using BussinessLogicTecnoPez.Produccion.Producto;
using BussinessLogicTecnoPez.AtencionCliente.Pedido;
using BussinessLogicTecnoPez.Produccion.FaenamientoEnvasado;
using DataAccessTecnoPez;

namespace BussinessLogicTecnoPez.Produccion.Producto
{
    [Serializable]
    [DBTable("stockProducto")]
    public class StockProducto : EntityBase<StockProducto>
    {
        private int idStock;

        [DBField("idStock", true, true)]
        public int IdStock
        {
            get { return idStock; }
            set { idStock = value; }
        }

        private DateTime fecha;

        [DBField("fecha", false, false)]
        public DateTime Fecha
        {
            get { return fecha; }
            set { fecha = value; }
        }

        private decimal cantidadMov;

        [DBField("cantidadMovimiento", false, false)]
        public decimal CantidadMovimiento
        {
            get { return cantidadMov; }
            set { cantidadMov = value; }
        }

        private decimal cantidadTotal;

        [DBField("cantidadTotal", false, false)]
        public decimal CantidadTotal
        {
            get { return cantidadTotal; }
            set { cantidadTotal = value; }
        }

        private Producto objProducto;

        [DBField("idProducto", false, false, true, "idProducto")]
        public Producto Producto
        {
            get { return objProducto; }
            set { objProducto = value; }
        }

        private Pedido pedido;

        [DBField("idPedido", false, false, true, "idPedido")]
        public Pedido Pedido
        {
            get { return pedido; }
            set { pedido = value; }
        }

        private PlanDeFaenamientoEnvasado objPlan;

        [DBField("idPlanFaenamiento", false, false, true, "idPlanFaenamiento")]
        public PlanDeFaenamientoEnvasado PlanDeFaenamientoEnvasado
        {
            get { return objPlan; }
            set { objPlan = value; }
        }

        /// <summary>
        /// Metodo que dado un producto devuelve su ultimo movimiento.
        /// 
        /// </summary>
        /// <param name="parametro"></param>
        /// <returns></returns>
        public static StockProducto obtenerUltimoEstadoDeStock(Producto parametro)
        {

            using (SQL cnn = new SQL())
            {
                cnn.SqlString = "SELECT     TOP (1) idStock " +
                                "   FROM         stockProducto" +
                                " WHERE     (idProducto = ?)" +
                                " ORDER BY fecha DESC ";
                System.Data.OleDb.OleDbDataReader dr;
                dr = cnn.GetDataReader(parametro.IdProducto);
                if (dr.Read())
                {
                    return StockProducto.getManager.GetOneByPrimaryKey(dr.GetInt32(0));
                }
                else
                {
                    return null;
                }
            }
        }

        /// <summary>
        /// Metodo para generar en memoria movimientos de stock
        /// por entradas de plandes de faenamiento.
        /// </summary>
        /// <param name="insumoEntrante"></param>
        /// <param name="movimiento"></param>
        /// <param name="fechaMovimiento"></param>
        /// <param name="idPedidoProveedor"></param>
        /// <returns></returns>
        public static StockProducto incorporarStockDesdePlanFaenamiento(Producto productoEntrante, decimal movimiento, DateTime fechaMovimiento, int idPlanFaenamiento)
        {
            StockProducto result = new StockProducto();

            using (SQL cnn = new SQL())
            {
                cnn.SqlString = "SELECT     TOP (1) cantidadTotal " +
                                "   FROM         stockProducto" +
                                " WHERE     (idProducto = ?)" +
                                " ORDER BY fecha DESC ";
                System.Data.OleDb.OleDbDataReader dr;
                dr = cnn.GetDataReader(productoEntrante.IdProducto);
                if (dr.Read())
                {
                    result.CantidadTotal = dr.GetDecimal(0);
                }
                else
                {
                    result.CantidadTotal = 0;
                }
                dr.Close();
                result.Producto = productoEntrante;
                result.cantidadMov = movimiento;
                result.CantidadTotal += movimiento;
                result.fecha = fechaMovimiento;
                PlanDeFaenamientoEnvasado p = PlanDeFaenamientoEnvasado.getManager.GetOneByPrimaryKey(idPlanFaenamiento);
                result.PlanDeFaenamientoEnvasado = p;
            }

            return result;

        }

        /// <summary>
        /// Metodo para generar en memoria movimientos de stock
        /// por salidas de pedidos.
        /// </summary>
        /// <returns></returns>
        public static StockProducto quitarStockDesdePedido(Producto productoSaliente, decimal movimiento, DateTime fechaMovimiento, int idPedido)
        {
            StockProducto result = new StockProducto();

            using (SQL cnn = new SQL())
            {
                cnn.SqlString = "SELECT     TOP (1) cantidadTotal " +
                                "   FROM         stockProducto" +
                                " WHERE     (idProducto = ?)" +
                                " ORDER BY fecha DESC ";
                System.Data.OleDb.OleDbDataReader dr;
                dr = cnn.GetDataReader(productoSaliente.IdProducto);
                if (dr.Read())
                {
                    result.CantidadTotal = dr.GetDecimal(0);
                }
                else
                {
                    result.CantidadTotal = 0;
                }
                dr.Close();
                result.Producto = productoSaliente;
                result.cantidadMov = movimiento;
                result.CantidadTotal -= movimiento;
                result.fecha = fechaMovimiento;
                Pedido p = Pedido.getManager.GetOneByPrimaryKey(idPedido);
                result.Pedido = p;
            }

            return result;

        }

        public static List<StockProducto> GetPronosticoProducto(Producto objProducto, DateTime desde, DateTime hasta)
        {
            List<StockProducto> objList = new List<StockProducto>();
            using (SQL objSql = new SQL())
            {
                string strSql = "SELECT SUM(CANTIDADMOVIMIENTO) CANTIDAD, MONTH(FECHA) MES, YEAR(FECHA) ANIO " +
                                "FROM STOCKPRODUCTO " +
                                "WHERE IDPRODUCTO=? AND CANTIDADMOVIMIENTO>0 AND FECHA > ? " +
                                "GROUP BY MONTH(FECHA), YEAR(FECHA) " +
                                "ORDER BY MONTH(FECHA), YEAR(FECHA)";
                objSql.SqlString = strSql;
                System.Data.OleDb.OleDbDataReader dr;
                object[] objValues = new object[2];
                objValues[0] = objProducto.IdProducto;
                objValues[1] = desde;
                dr = objSql.GetDataReader(objValues);

                decimal[] vecCantidades = new decimal[5];
                vecCantidades[0] = 0;
                vecCantidades[1] = 0;
                vecCantidades[2] = 0;
                vecCantidades[3] = 0;
                vecCantidades[4] = 0;

                StockProducto objStock;
                while (dr.Read())
                {
                    objStock = new StockProducto();
                    objStock.CantidadTotal = Convert.ToDecimal(dr["CANTIDAD"]);
                    objStock.Fecha = new DateTime(dr.GetInt32(2), dr.GetInt32(1), 1);
                    objStock.Producto = objProducto;

                    StockProducto.AgregarAlFinal(ref vecCantidades, objStock.CantidadTotal);
                    objList.Add(objStock);
                }
                dr.Close();
                //calcula tendencias
                DateTime datFechaFin = new DateTime(DateTime.Today.Year, DateTime.Today.Month, 1);
                datFechaFin = datFechaFin.AddMonths(1);
                while (datFechaFin <= hasta)
                {
                    objStock = new StockProducto();
                    objStock.CantidadTotal = StockProducto.GetNewValor(vecCantidades);
                    objStock.Fecha = datFechaFin;
                    objStock.Producto = objProducto;

                    objList.Add(objStock);

                    StockProducto.AgregarAlFinal(ref vecCantidades, objStock.CantidadTotal);
                    datFechaFin = datFechaFin.AddMonths(1);
                }

            }
            return objList;
        }
        private static void AgregarAlFinal(ref decimal[] vecCantidades, decimal valor)
        {
            vecCantidades[0] = vecCantidades[1];
            vecCantidades[1] = vecCantidades[2];
            vecCantidades[2] = vecCantidades[3];
            vecCantidades[3] = vecCantidades[4];
            vecCantidades[4] = valor;
        }
        private static decimal GetNewValor(decimal[] vecCantidades)
        {
            int cantidad = 0;
            decimal result = 0;
            result += vecCantidades[0];
            result += vecCantidades[1];
            result += vecCantidades[2];
            result += vecCantidades[3];
            result += vecCantidades[4];

            if (vecCantidades[0] != 0)
                cantidad++;
            if (vecCantidades[1] != 0)
                cantidad++;
            if (vecCantidades[2] != 0)
                cantidad++;
            if (vecCantidades[3] != 0)
                cantidad++;
            if (vecCantidades[4] != 0)
                cantidad++;

            if (cantidad != 0)
                return result / cantidad;
            else
                return 0;
        }
    }
}
